﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Web.UI.WebControls;
using ActionModel.Utility;

namespace FilesArranger
{
	public class SiteBrowseTreeToDo : ITreeToDo
	{
		DivNode[] ITreeToDo.LoadChildren(string valuePath)
		{
			string physicalPath = HttpContext.Current.Server.MapPath(valuePath);

			DirectoryInfo folder = new DirectoryInfo(physicalPath);

			int preLength = HttpContext.Current.Server.MapPath("/").Length - 1;
			DirectoryInfo[] directories = folder.GetDirectories();
			DivNode[] folderNodes = directories.Select(f => CastToTreeNode(f)).ToArray();
			FileInfo[] files = folder.GetFiles();
			DivNode[] fileNodes = files.Select(f => CastToTreeNode(f)).ToArray();
			DivNode[] nodes = folderNodes.Concat(fileNodes).ToArray();

			return nodes;
		}


		void ITreeToDo.DeleteChildNode(string valuePath, DivNode node, ToDoCallBack toDoCallback)
		{
			bool result = false;
			string message = string.Empty;
			string physicalPath = HttpContext.Current.Server.MapPath(valuePath);
			if (node.ExpandCollapseStatus != ExpandCollapseIconEnum.None)
			{
				string filePath = physicalPath + "\\" + node.Value;
				if (File.Exists(filePath))
				{
					File.Delete(filePath);
					toDoCallback(true, string.Empty);
				}
				else
				{
					toDoCallback(true, "directory is not exists.");
				}
			}
			else
			{
				string folderPath = physicalPath + "\\" + node.Value;
				if (Directory.Exists(folderPath))
				{
					Directory.Delete(folderPath, true);
					toDoCallback(true, string.Empty);
				}
				else
				{
					toDoCallback(true, "directory is not exists.");
				}
			}


			toDoCallback.Invoke(result, message);
		}



		int preLength = HttpContext.Current.Server.MapPath("/").Length - 1;
		public static DivNode CastToTreeNode(DirectoryInfo directory)
		{
			DivNode treeNode = new DivNode();

			treeNode.NavigateHref = "javascript:void 0;";
			treeNode.Text = directory.Name;
			treeNode.Value = directory.Name;

			treeNode.TypeIcon = "_folder";
			treeNode.ToolTip = JSONSerializer.ToJSON(new
			{
				CreationTimeUtc = directory.CreationTimeUtc,
				LastAccessTimeUtc = directory.LastAccessTimeUtc,
				LastWriteTimeUtc = directory.LastWriteTimeUtc,
			}).Replace("\"", "&#34;");
			treeNode.ImageToolTip = directory.FullName;
			treeNode.ExpandCollapseStatus = ExpandCollapseIconEnum.PopulateExpand;
			treeNode.ShowTypeIcon = true;
			treeNode.ShowCheckBox = false;

			return treeNode;
		}

		public static DivNode CastToTreeNode(FileInfo file)
		{
			DivNode treeNode = new DivNode();

			treeNode.NavigateHref = file.Name;//
			treeNode.Text = file.Name;
			treeNode.Value = file.Name;

			treeNode.TypeIcon = file.Extension.Substring(1);

			treeNode.ToolTip = JsonSerializer.ToJSON(new
			{
				CreationTimeUtc = file.CreationTimeUtc,
				LastAccessTimeUtc = file.LastAccessTimeUtc,
				LastWriteTimeUtc = file.LastWriteTimeUtc,
			}).Replace("\"", "&#34;");
			treeNode.ImageToolTip = file.FullName;
			treeNode.ExpandCollapseStatus = ExpandCollapseIconEnum.None;
			treeNode.ShowTypeIcon = true;
			treeNode.ShowCheckBox = false;

			return treeNode;
		}


		DivNode[] ITreeToDo.Refresh(IDictionary<string, object> pathsExpandRecord)
		{
			string physicalPath = HttpContext.Current.Server.MapPath("/"); //Root
			DirectoryInfo folder = new DirectoryInfo(physicalPath);
			//DivNode node = CastToTreeNode(folder);
			DirectoryInfo[] directories = folder.GetDirectories();
			DivNode[] rootFolderNodes = directories.Select(f => CastToTreeNode(f)).ToArray();
			string[] folderNames = rootFolderNodes.Select(n => n.Value).ToArray();

			DivNode[] expandNodes = pathsExpandRecord.Select(kValue => fillFolderInfo(kValue, string.Empty)).ToArray();
			//IDictionary<string, object> rootExpandRecord = ((IDictionary<string, object>)pathsExpandRecord["/"]);
			//DivNode[] expandNodes = rootExpandRecord.Select(kValue => fillFolderInfo(kValue, string.Empty)).ToArray();

			foreach (DivNode dNode in expandNodes)
			{
				int index = Array.IndexOf(folderNames, dNode.Value);
				if (index != -1)
				{
					rootFolderNodes[index] = dNode;
				}
			}

			FileInfo[] files = folder.GetFiles();
			DivNode[] fileNodes = files.Select(f => CastToTreeNode(f)).ToArray();
			DivNode[] rootNodes = rootFolderNodes.Concat(fileNodes).ToArray();


			return rootNodes;
		}

		private DivNode fillFolderInfo(KeyValuePair<string, object> kValue, string prePath)
		{
			string physicalPath = HttpContext.Current.Server.MapPath(prePath + "/" + kValue.Key);
			DirectoryInfo folder = new DirectoryInfo(physicalPath);
			DivNode node = CastToTreeNode(folder);
			node.ExpandCollapseStatus = ExpandCollapseIconEnum.Collapse;
			DirectoryInfo[] directories = folder.GetDirectories();
			node.ChildNodes = directories.Select(f => CastToTreeNode(f)).ToArray();
			string[] folderNames = node.ChildNodes.Select(n => n.Value).ToArray();

			IDictionary<string, object> subRecord = (IDictionary<string, object>)kValue.Value;
			DivNode[] expandNodes = subRecord.Select(kV => fillFolderInfo(kV, kValue.Key)).ToArray();

			foreach (DivNode dNode in expandNodes)
			{
				int index = Array.IndexOf(folderNames, dNode.Value);
				if (index != -1)
				{
					node.ChildNodes[index] = dNode;
				}
			}
			FileInfo[] files = folder.GetFiles();
			DivNode[] fileNodes = files.Select(f => CastToTreeNode(f)).ToArray();
			node.ChildNodes = node.ChildNodes.Concat(fileNodes).ToArray();

			return node;
		}



		void ITreeToDo.MoveFolderNode(string sourcePath, string destinationPath, ToDoCallBack toDoCallback)
		{
			string sourceDirName = HttpContext.Current.Server.MapPath(sourcePath);
			string destDirName = HttpContext.Current.Server.MapPath(destinationPath);
			try
			{
				Directory.Move(sourceDirName, destDirName);
				toDoCallback(true, null);
			}
			catch (Exception ex)
			{
				if (!(ex is System.Threading.ThreadAbortException))
				{
					toDoCallback(false, ex.Message);
				}
			}
		}

		void ITreeToDo.MoveFileNode(string sourcePath, string destinationPath, ToDoCallBack toDoCallback)
		{
			string sourceFileName = HttpContext.Current.Server.MapPath(sourcePath);
			string destFileName = HttpContext.Current.Server.MapPath(destinationPath);
			try
			{
				File.Move(sourceFileName, destFileName);
				toDoCallback(true, null);
			}
			catch (Exception ex)
			{
				if (!(ex is System.Threading.ThreadAbortException))
				{
					toDoCallback(false, ex.Message);
				}
			}
		}


		void ITreeToDo.CreateFolderNode(string sourcePath, DivNode node, ToDoCallBack toDoCallback)
		{
			try
			{
				string physicalPath = HttpContext.Current.Server.MapPath(sourcePath + node.Value);
				DirectoryInfo folder = Directory.CreateDirectory(physicalPath);

				toDoCallback(true, "");
			}
			catch (Exception ex)
			{
				if (!(ex is System.Threading.ThreadAbortException))
				{
					toDoCallback(false, ex.Message);
				}
			}
		}

		void ITreeToDo.CreateFileNode(string sourcePath, DivNode node, ToDoCallBack toDoCallback)
		{
			try
			{
				string filePath = HttpContext.Current.Server.MapPath(sourcePath) + "\\" + node.Value;
				File.Create(filePath).Close();

				toDoCallback(true, "");
			}
			catch (Exception ex)
			{
				if (!(ex is System.Threading.ThreadAbortException))
				{
					toDoCallback(false, ex.Message);
				}
			}
		}
	}
}